import pandas as pd
import numpy as np
import talib as ta


def bbi_signal(data):
    data = data.copy()
    close = data['close'].values
    ma1 = ta.SMA(close, timeperiod=3)
    ma2 = ta.SMA(close, timeperiod=6)
    ma3 = ta.SMA(close, timeperiod=12)
    ma4 = ta.SMA(close, timeperiod=24)
    bbi = (ma1 + ma2 + ma3 + ma4) / 4
    data['bbi'] = bbi
    data.loc[:, 'signal'] = np.where(data['close'] > data['bbi'], 1, 0)
    return data[['signal']]


def bias_signal(data):
    data = data.copy()
    close = data['close'].values
    sma6 = ta.SMA(close, timeperiod=6)
    bias = (close - sma6) / sma6 * 100
    data['bias'] = bias
    data.loc[:, 'signal'] = np.where((data['bias'] < 0) & (data['bias'] > data['bias'].shift(1)), 1,
                                     np.where((data['bias'] > 0) & (data['bias'] < data['bias'].shift(1)), 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]


def cci_signal(data):
    data = data.copy()
    high = data['high'].values
    low = data['low'].values
    close = data['close'].values
    cci = ta.CCI(high, low, close, timeperiod=14)
    data['cci'] = cci
    data.loc[:, 'signal'] = np.where((data['cci'].shift(1) < 100) & (data['cci'] > 100), 1,
                                     np.where((data['cci'].shift(1) > -100) & (data['cci'] < -100), 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]


def dma_signal(data):
    data = data.copy()
    close = data['close'].values
    dma = ta.DEMA(close, timeperiod=10) - ta.DEMA(close, timeperiod=50)
    data['dma'] = dma
    data.loc[:, 'signal'] = np.where(data['dma'] > 0, 1, 0)
    return data[['signal']]


def expma_signal(data):
    data = data.copy()
    close = data['close'].values
    ema_short = ta.EMA(close, timeperiod=12)
    ema_long = ta.EMA(close, timeperiod=26)
    data['ema_short'] = ema_short
    data['ema_long'] = ema_long
    data.loc[:, 'signal'] = np.where(data['ema_short'] > data['ema_long'], 1, 0)
    return data[['signal']]


def kdj_signal(data):
    data = data.copy()
    high = data['high'].values
    low = data['low'].values
    close = data['close'].values
    k, d = ta.STOCH(high, low, close)
    data['K'] = k
    data['D'] = d
    data.loc[:, 'signal'] = np.where(
        (data['K'] < 20) & (data['K'].shift(1) < data['D'].shift(1)) & (data['K'] > data['D']), 1,
        np.where((data['K'] > 80) & (data['K'].shift(1) > data['D'].shift(1)) & (
                data['K'] < data['D']), 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]


def macd_signal(data):
    data = data.copy()
    close = data['close'].values
    dif, dea, hist = ta.MACD(close)
    data['DIF'] = dif
    data['DEA'] = dea
    data.loc[:, 'signal'] = np.where(data['DIF'] > data['DEA'], 1, 0)
    return data[['signal']]


def mfi_signal(data):
    data = data.copy()
    high = data['high'].values
    low = data['low'].values
    close = data['close'].values
    volume = data['volume'].values
    mfi = ta.MFI(high, low, close, volume, timeperiod=14)
    data['mfi'] = mfi
    data.loc[:, 'signal'] = np.where((data['mfi'] < 20) & (data['mfi'].shift(1) < data['mfi']), 1,
                                     np.where((data['mfi'] > 80) & (data['mfi'].shift(1) > data['mfi']), 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]


def mi_signal(data):
    data = data.copy()
    close = data['close'].values
    mi = ta.MOM(close, timeperiod=10)
    data['mi'] = mi
    data.loc[:, 'signal'] = np.where(data['mi'] < 0, 1, 0)
    return data[['signal']]


def mtm_signal(data):
    data = data.copy()
    close = data['close'].values
    mtm = ta.MOM(close, timeperiod=10)
    data['mtm'] = mtm
    data.loc[:, 'signal'] = np.where(data['mtm'] > 0, 1, 0)
    return data[['signal']]


def priceosc_signal(data):
    data = data.copy()
    close = data['close'].values
    ppo = ta.PPO(close)
    data['ppo'] = ppo
    data.loc[:, 'signal'] = np.where(data['ppo'] > 0, 1, 0)
    return data[['signal']]


def psy_signal(data):
    data = data.copy()
    close = data['close'].values
    up_days = (close - np.roll(close, 1) > 0).astype(float)
    psy = ta.SMA(up_days, timeperiod=12) * 100
    data['psy'] = psy
    data.loc[:, 'signal'] = np.where(data['psy'] < 30, 1, np.where(data['psy'] > 70, 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]


def roc_signal(data):
    data = data.copy()
    close = data['close'].values
    roc = ta.ROC(close, timeperiod=12)
    data['roc'] = roc
    data.loc[:, 'signal'] = np.where((data['roc'] > 0) & (data['roc'].shift(1) < 0), 1,
                                     np.where((data['roc'] < 0) & (data['roc'].shift(1) > 0), 0, np.nan))
    data['signal'].fillna(method='ffill', inplace=True)
    return data[['signal']]
